
#pragma once

#if defined(__GNUC__) || defined(__MINGW__) || defined(__MINGW32__)
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Weffc++"
#endif

#include "libden/meta/can_recursive_iteration.h"

namespace Den{

    template<class Container, class ConcreteWay > 
    class IteratorBaseWrapper: 
        public TWay<Container, ConcreteWay>::iterator
    {
        typedef IteratorBaseWrapper
            My;
        typedef typename 
            ::std::add_const<Container>::type
                cv;
        typedef typename 
            ::std::remove_const<Container>::type
                no_cv;
        friend 
            class IteratorBaseWrapper<cv, ConcreteWay>;
        friend 
            class IteratorBaseWrapper<no_cv, ConcreteWay>;
    public:
        typedef TWay<Container, ConcreteWay>
            way;
        typedef typename way::iterator
            iterator;
        typedef typename iterator::value_type
            value_type;

        enum { IS_WRAPPER = 1 };
        enum { IS_REVERSE = way::IS_REVERSE };

        enum { CAN_RECURSE =
            is_iterator_recursive<My, ConcreteWay>::value };

        enum { IS_CONST = ::std::is_const<Container>::value ||
            way::IS_CONST };

        typedef typename ::std::conditional<IS_CONST, cv, no_cv>::type
            contaiter_type;

        IteratorBaseWrapper();
        IteratorBaseWrapper(cv& c);
        IteratorBaseWrapper(no_cv& c);
        IteratorBaseWrapper(cv& c, const iterator& cur);
        IteratorBaseWrapper(no_cv& c, const iterator& cur);

        IteratorBaseWrapper(const IteratorBaseWrapper& rhs);

        template<class U>
            IteratorBaseWrapper(const IteratorBaseWrapper<U, ConcreteWay>& rhs);

        IteratorBaseWrapper& operator=(no_cv& c);
        IteratorBaseWrapper& operator=(cv& c);
        
        template<class U>
            IteratorBaseWrapper& 
                operator=(const IteratorBaseWrapper<U, ConcreteWay>& rhs);
        
        operator bool()const; 
        bool operator!()const;

        bool Empty()const;
        bool Beg()const;
        bool End()const;
        
        bool operator!=(const IteratorBaseWrapper& rhs)const;
        bool operator==(const IteratorBaseWrapper& rhs)const;
    private:
        contaiter_type* mContainer;
    };

}//namespace Den


#if defined(__GNUC__) || defined(__MINGW__) || defined(__MINGW32__)
    #pragma GCC diagnostic pop
#endif
